﻿using System;
using System.Collections.Generic;
using System.Linq;
using BCCommon;
using BCCommon.Enums;
using BCCommon.FMISEnums;
using BCCommon.OAEnums;
using BCCommon.OAEnums.Workflow;
using BCCommon.SCMEnums;
using BCEntity.OA.TeamWorks.TaskRecord;
using BCData.FMIS.PaymentReceiptCallback;
using BCData.FMIS.PaymentReceiptCertificate;
using BCData.OA.TeamWorks.FMISTaskRecord;
using BCData.OA.TeamWorks.TaskRejectRecord;
using BCData.OA.TeamWorks.TaskRejectReplyRecord;
using BCDto.MySql.Admin;
using BCDto.OA.TeamWorks.TaskRecord;
using BCDto.OA.TeamWorks.TaskRecordCount;
using BCDto.OA.TeamWorks.TaskRejectRecord;
using BCDto.OA.TeamWorks.TaskRejectReplyRecord;
using BCDto.OA.Workflow.WorkflowActivityInstance;
using BCService.Utils;
using BCService.CommonService.Payment.PaymentRecord;
using BCService.OA.Workflow.WorkflowActivityInstanceBusiness;
using BCService.SCM.VehicleSaleContractIncomeRecord;

namespace BCService.OA.TeamWorks.FMISTaskRecordService
{
    public class FMISTaskRecordService : IFMISTaskRecordService
    {
        private readonly IFMISTaskRecordData fMISTaskRecordData;
        private readonly ITaskRejectRecordData taskRejectRecordData;
        private readonly ITaskRejectReplyRecordData taskRejectReplyRecordData;
        private readonly IPaymentReceiptCertificateData paymentReceiptCertificateData;
        private readonly IPaymentReceiptCallbackData paymentReceiptCallbackData;
        private readonly IWorkflowActivityInstanceBusinessService workflowActivityInstanceBusinessService;
        private readonly IVehicleSaleContractIncomeRecordService vehicleSaleContractIncomeRecordService;
        private readonly ICommonPaymentRecordService paymentRecordService;

        public FMISTaskRecordService(IFMISTaskRecordData fMISTaskRecordData,
            ITaskRejectRecordData taskRejectRecordData,
            ITaskRejectReplyRecordData taskRejectReplyRecordData,
            IPaymentReceiptCertificateData paymentReceiptCertificateData,
            IPaymentReceiptCallbackData paymentReceiptCallbackData,
            IWorkflowActivityInstanceBusinessService workflowActivityInstanceBusinessService,
            IVehicleSaleContractIncomeRecordService vehicleSaleContractIncomeRecordService,
            ICommonPaymentRecordService paymentRecordService)
        {
            this.fMISTaskRecordData = fMISTaskRecordData;
            this.taskRejectRecordData = taskRejectRecordData;
            this.taskRejectReplyRecordData = taskRejectReplyRecordData;
            this.paymentReceiptCertificateData = paymentReceiptCertificateData;
            this.paymentReceiptCallbackData = paymentReceiptCallbackData;
            this.workflowActivityInstanceBusinessService = workflowActivityInstanceBusinessService;
            this.vehicleSaleContractIncomeRecordService = vehicleSaleContractIncomeRecordService;
            this.paymentRecordService = paymentRecordService;
        }

        #region 步骤扩展方法
        /// <summary>
        /// 下发通用入账任务
        /// </summary>
        /// <param name="workflowActivityInstanceId">工作流活动实例Id</param>
        /// <returns></returns>
        public FMISTaskRecordDto CreateAccountTask(long workflowActivityInstanceId)
        {
            return null;
        }

        /// <summary>
        /// 下发通用付款任务
        /// </summary>
        /// <param name="workflowActivityInstanceId">工作流活动实例Id</param>
        /// <returns></returns>
        public FMISTaskRecordDto CreatePaymentTask(long workflowActivityInstanceId)
        {
            return null;
        }

        /// <summary>
        /// 下发通用收款任务
        /// </summary>
        /// <param name="workflowActivityInstanceId">工作流活动实例Id</param>
        /// <returns></returns>
        public FMISTaskRecordDto CreateReceiptTask(long workflowActivityInstanceId)
        {
            return null;
        }

        /// <summary>
        /// 处理异常信息
        /// </summary>
        /// <param name="workflowActivityInstanceId"></param>
        /// <param name="handledRemark">处理备注</param>
        /// <returns></returns>
        public IEnumerable<FMISTaskRecordDto> HandledException(long workflowActivityInstanceId, string handledRemark)
        {
            var instanceDto = this.workflowActivityInstanceBusinessService.GetInstanceInfo(workflowActivityInstanceId);
            var fmisTaskRecords = this.fMISTaskRecordData.Get(workflowActivityInstanceId).GetAwaiter().GetResult();
            foreach (var taskRecord in fmisTaskRecords)
            {
                taskRecord.HandledRemark = handledRemark;
                taskRecord.IsException = false;
            }
            if (!this.fMISTaskRecordData.UpdateTaskException(fmisTaskRecords).GetAwaiter().GetResult())
            {
                throw new ArgumentException("处理任务异常记录失败");
            }
            return fmisTaskRecords.As<IEnumerable<FMISTaskRecordDto>>();
        }

        #endregion

        /// <summary>
        /// 获取财务业务任务单列表
        /// </summary>
        /// <param name="executerAdminId"></param>
        /// <param name="date"></param>
        /// <param name="startDate">开始日期</param>
        /// <param name="endDate">结束日期</param>
        /// <param name="handleStatus"></param>
        /// <param name="isException"></param>
        /// <param name="taskType"></param>
        /// <param name="sortName"></param>
        /// <param name="ascending"></param>
        /// <param name="taskExecuterFullName"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="companyId"></param>
        /// <returns></returns>
        public PageableList<FMISTaskRecordDto> Query(long? executerAdminId, DateTime? date, DateTime? startDate, DateTime? endDate, OATaskHandleStatus? handleStatus, FMISTaskType? taskType,
            bool? isException, string sortName, bool? ascending, string taskExecuterFullName, int pageIndex, int pageSize, int? companyId,
            string saleContractNo, string purchaseContractNo, string vehicleBrandName, string buyerName)
        {
            var result = new PageableList<FMISTaskRecordDto>();

            var (data, dataCount) = this.fMISTaskRecordData.Query(executerAdminId, date, startDate, endDate, handleStatus,
                taskType, isException, sortName, companyId, ascending, taskExecuterFullName,
                saleContractNo, purchaseContractNo, vehicleBrandName, buyerName, pageIndex, pageSize).GetAwaiter().GetResult();
            result.Items = data.As<List<FMISTaskRecordDto>>();
            result.Count = dataCount;
            foreach (var item in result.Items)
            {
                var activityInstance = workflowActivityInstanceBusinessService.GetInstanceInfo(item.WorkflowActivityInstanceId);
                var referenceDto = this.workflowActivityInstanceBusinessService.GetActivityInstanceReference(item.WorkflowActivityInstanceId);
                item.ActivityInstance = activityInstance.As<WorkflowActivityInstanceDto>();
                item.StepInstance = activityInstance.Steps.First(p => p.TaskStep == item.CurrentlyStep);
                item.ExtendMethodInstances = activityInstance.ExtendMethods.Where(p => p.TaskStep == item.CurrentlyStep).ToList();
                item.ActivityInstance.Steps = null;
                item.ActivityInstance.ExtendMethods = null;
                item.ReferenceBusinessType = referenceDto.BusinessType;
                item.WorkflowType = referenceDto.WorkflowType;
                item.ReferenceNo = referenceDto.ReferenceNo;
            }
           
            return result;
        }

        public IEnumerable<TaskRejectRecordDto> RejectRecords(AdminDto adminDto, long workflowActivityInstanceId)
        {
            long? adminId = null;
            if (adminDto != null)
            {
                adminId = adminDto.AdminId;
            }
            var list = this.taskRejectRecordData.GetByWorkflowActivityInstanceId(workflowActivityInstanceId, adminId).GetAwaiter().GetResult().As<IEnumerable<TaskRejectRecordDto>>();
            foreach (var item in list)
            {
                item.Replys = this.taskRejectReplyRecordData.GetEntities(workflowActivityInstanceId, item.TaskRejectRecordId).GetAwaiter().GetResult().As<List<TaskRejectReplyRecordDto>>();
            }
            return list;
        }

        public FMISTaskRecordCountDto TodayRecordCount(long? executerAdminId)
        {
            FMISTaskRecordCountDto todayRecordCountDto = this.fMISTaskRecordData.TodayRecordCount(executerAdminId).GetAwaiter().GetResult().As<FMISTaskRecordCountDto>();
            FMISTaskRecordCountDto unfinishedRecordCountDto = this.fMISTaskRecordData.UnfinishedCount(executerAdminId).GetAwaiter().GetResult().As<FMISTaskRecordCountDto>();

            todayRecordCountDto.PendingCount += unfinishedRecordCountDto.PendingCount;
            todayRecordCountDto.RejectedCount += unfinishedRecordCountDto.RejectedCount;
            todayRecordCountDto.PausedCount += unfinishedRecordCountDto.PausedCount;
            return todayRecordCountDto;
        }

        #region 步骤扩展方法回调
        #region 更新任务实收实付金额
        public IEnumerable<FMISTaskRecordEntity> UpdateTaskActualReceiptPaymentAmount(long workflowActivityInstanceId)
        {
            var instanceDto = this.workflowActivityInstanceBusinessService.GetInstanceInfo(workflowActivityInstanceId);

            var referenceEntity = this.workflowActivityInstanceBusinessService.GetActivityInstanceReference(workflowActivityInstanceId);

            var paymentReceiptCertificateEntity = this.paymentReceiptCertificateData.Get(referenceEntity.ReferenceNo).GetAwaiter().GetResult();

            var fmisTaskRecords = this.fMISTaskRecordData.GetWithCurrentlyStep(workflowActivityInstanceId).GetAwaiter().GetResult();

            if (paymentReceiptCertificateEntity.Amount != paymentReceiptCertificateEntity.ActualAmount)
            {
                //string exceptionRemark = string.Format("{0}异常：", paymentReceiptCertificateEntity.PaymentReceiptCertificateCategory.GetDescriptionString());

                //if (paymentReceiptCertificateEntity.Amount > paymentReceiptCertificateEntity.ActualAmount)
                //{
                //    exceptionRemark = string.Format("{0} 少 {1}元", paymentReceiptCertificateEntity.PaymentReceiptCertificateCategory.GetDescriptionString(), paymentReceiptCertificateEntity.Amount - paymentReceiptCertificateEntity.ActualAmount);
                //}
                //else
                //{
                //    exceptionRemark = string.Format("{0} 多 {1}元", paymentReceiptCertificateEntity.PaymentReceiptCertificateCategory.GetDescriptionString(), paymentReceiptCertificateEntity.ActualAmount - paymentReceiptCertificateEntity.Amount);
                //}
                foreach (var taskRecord in fmisTaskRecords)
                {
                    taskRecord.IsException = paymentReceiptCertificateEntity.IsException;
                    taskRecord.ExceptionDescription = paymentReceiptCertificateEntity.ExceptionDescription;
                    if (paymentReceiptCertificateEntity.PaymentReceiptCertificateCategory == FMISPaymentReceiptCertificateType.Income)
                    {
                        taskRecord.ActualReceiptAmount = paymentReceiptCertificateEntity.ActualAmount;
                    }
                    else
                    {
                        taskRecord.ActualPaidAmount = paymentReceiptCertificateEntity.ActualAmount;
                    }
                    taskRecord.HandledRemark = paymentReceiptCertificateEntity.Remark;
                }
                if (!this.fMISTaskRecordData.UpdateTaskException(fmisTaskRecords).GetAwaiter().GetResult())
                {
                    throw new ArgumentException("修改任务实际收付款金额异常记录失败");
                }
            }
            foreach (var taskRecord in fmisTaskRecords)
            {
                if (paymentReceiptCertificateEntity.PaymentReceiptCertificateCategory == FMISPaymentReceiptCertificateType.Income)
                {
                    taskRecord.ActualReceiptAmount = paymentReceiptCertificateEntity.ActualAmount;
                }
                else
                {
                    taskRecord.ActualPaidAmount = paymentReceiptCertificateEntity.ActualAmount;
                }
                taskRecord.HandledRemark = paymentReceiptCertificateEntity.Remark;
            }
            if (!this.fMISTaskRecordData.UpdateActualReceiptPaymentAmount(fmisTaskRecords).GetAwaiter().GetResult())
            {
                throw new ArgumentException("修改任务实际收付款金额记录失败");
            }
            //增加合同收益记录信息
            var task = fmisTaskRecords.First(s => s.CurrentlyStep == instanceDto.CurrentlyStep);

            switch (instanceDto.WorkflowKey.As<OATaskBusinessType>())
            {
                case OATaskBusinessType.WorkflowBusiness_DepositReceipt_Sale:
                    vehicleSaleContractIncomeRecordService.Add(paymentReceiptCertificateEntity, VehicleSaleIncomeType.Deposit, task.TaskRecordId, task.TaskExecuterAdminId.Value, task.TaskExecuterFullName);
                    break;
                case OATaskBusinessType.WorkflowBusiness_LastPaymentReceipt_Sale:
                    vehicleSaleContractIncomeRecordService.Add(paymentReceiptCertificateEntity, VehicleSaleIncomeType.DueBalance, task.TaskRecordId, task.TaskExecuterAdminId.Value, task.TaskExecuterFullName);
                    break;
                case OATaskBusinessType.WorkflowBusiness_PeriodizationReceipt_Loan:
                    vehicleSaleContractIncomeRecordService.Add(paymentReceiptCertificateEntity, VehicleSaleIncomeType.InstalmentRepayment, task.TaskRecordId, task.TaskExecuterAdminId.Value, task.TaskExecuterFullName);
                    break;
                case OATaskBusinessType.WorkflowBusiness_DownPaymentReceipt_Sale:
                    vehicleSaleContractIncomeRecordService.Add(paymentReceiptCertificateEntity, VehicleSaleIncomeType.DownPayment, task.TaskRecordId, task.TaskExecuterAdminId.Value, task.TaskExecuterFullName);
                    break;
                case OATaskBusinessType.WorkflowBusiness_VehicleFeeTransferCashReceipt_VehicleFee:
                    {
                        var paymentReceiptCallbackEntity = this.paymentReceiptCallbackData.GetPaymentReceiptCallbackByPaymentReceiptCertificateNoAsync(referenceEntity.ReferenceNo).GetAwaiter().GetResult();
                        var paymentRecordList = this.paymentRecordService.GetEntityByReferenceNumberAsync(paymentReceiptCallbackEntity.CallbackNo);
                        var paymentRecord = paymentRecordList.First(p => p.Status != PaymentResultType.Success);
                        var paymentRecordDto = this.paymentRecordService.UpdatePaymentRecordStatusSuccess(paymentRecord.PaymentRecordId);
                    }
                    break;
                case OATaskBusinessType.WorkflowBusiness_LateFeeReceipt_Sale:
                    {
                        vehicleSaleContractIncomeRecordService.Add(paymentReceiptCertificateEntity, BCCommon.SCMEnums.VehicleSaleIncomeType.OverdueFine, task.TaskRecordId, task.TaskExecuterAdminId.Value, task.TaskExecuterFullName);
                    }
                    break;
                case OATaskBusinessType.WorkflowBusiness_PaymentReceipt_SaleFinancePenalty:
                    {
                        vehicleSaleContractIncomeRecordService.Add(paymentReceiptCertificateEntity, BCCommon.SCMEnums.VehicleSaleIncomeType.SaleFinancePenalty, task.TaskRecordId, task.TaskExecuterAdminId.Value, task.TaskExecuterFullName);
                    }
                    break;
                default:
                    break;
            }
            return fmisTaskRecords;

        }
        #endregion

        #region 更新任务实际结转金额
        public IEnumerable<FMISTaskRecordEntity> UpdateTaskActualCarryForwardAmount(long workflowActivityInstanceId)
        {
            var instanceDto = this.workflowActivityInstanceBusinessService.GetInstanceInfo(workflowActivityInstanceId);

            var referenceEntity = this.workflowActivityInstanceBusinessService.GetActivityInstanceReference(workflowActivityInstanceId);

            var paymentReceiptCertificateEntity = this.paymentReceiptCertificateData.Get(referenceEntity.ReferenceNo).GetAwaiter().GetResult();

            var fmisTaskRecords = this.fMISTaskRecordData.GetWithCurrentlyStep(workflowActivityInstanceId).GetAwaiter().GetResult();

            var total = paymentReceiptCertificateEntity.ActualAmount + paymentReceiptCertificateEntity.ServiceAmount;
            if (paymentReceiptCertificateEntity.Amount != total)
            {
                foreach (var taskRecord in fmisTaskRecords)
                {
                    taskRecord.IsException = paymentReceiptCertificateEntity.IsException;
                    taskRecord.ExceptionDescription = paymentReceiptCertificateEntity.ExceptionDescription;
                    if (paymentReceiptCertificateEntity.PaymentReceiptCertificateCategory == FMISPaymentReceiptCertificateType.Income)
                    {
                        taskRecord.ActualReceiptAmount = total;
                    }
                    else
                    {
                        taskRecord.ActualPaidAmount = total;
                    }
                    taskRecord.HandledRemark = paymentReceiptCertificateEntity.Remark;
                }
                if (!this.fMISTaskRecordData.UpdateTaskException(fmisTaskRecords).GetAwaiter().GetResult())
                {
                    throw new ArgumentException("修改任务实际收付款金额异常记录失败");
                }
            }
            foreach (var taskRecord in fmisTaskRecords)
            {
                if (paymentReceiptCertificateEntity.PaymentReceiptCertificateCategory == FMISPaymentReceiptCertificateType.Income)
                {
                    taskRecord.ActualReceiptAmount = total;
                }
                else
                {
                    taskRecord.ActualPaidAmount = total;
                }
                taskRecord.HandledRemark = paymentReceiptCertificateEntity.Remark;
            }
            if (!this.fMISTaskRecordData.UpdateActualReceiptPaymentAmount(fmisTaskRecords).GetAwaiter().GetResult())
            {
                throw new ArgumentException("修改任务实际收付款金额记录失败");
            }
            return fmisTaskRecords;
        }
        #endregion

        #region 更新任务修改后保证金金额
        public void UpdateDepositModifyApplyRecord(long workflowActivityInstanceId)
        {

        }
        #endregion
        #endregion
    }
}
